//
//  LightsController.m
//  SuperLight
//
//  Created by Charlie Liao on 14-4-24.
//  Copyright (c) 2014年 Charlie Liao. All rights reserved.
//

#import "LightController.h"

@implementation LightController

#pragma mark Init 单例实现

+ (LightController*)shareInstance
{
    static LightController *singleton;
    if (!singleton) {
        @synchronized(self) {
            singleton = [[super allocWithZone:NULL] init];
        }
    }
    return singleton;
}

+ (id)allocWithZone:(struct _NSZone *)zone
{
    return [self shareInstance];
}

- (id)init
{
    self = [super init];
    if (self) {
        dispatch_queue_t queue_t =  dispatch_queue_create("wifi_AsyncSocket", DISPATCH_QUEUE_SERIAL);
        mSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:queue_t];
        queue_t = NULL;
    }
    return self;
}

#pragma mark  Status

- (void)connect
{
    if (mSocket.isDisconnected) {
        NSError *err = nil;
        NSLog(@"连接 Robstep_HOST->%@ Robstep_PORT->%i", SERVER_IP_ADDR, SERVER_PORT);
        if([mSocket connectToHost:SERVER_IP_ADDR onPort:SERVER_PORT withTimeout:3 error:&err]) {
            
        } else {
            [self postNotificationName:ncLightConnectionFailed object:err];
            NSLog(@"connect err->%@", err);
        }
    }
}

- (void)disconnect
{
    [mSocket disconnectAfterWriting];
}

- (BOOL)isConnected
{
    return mSocket.isConnected;
}

#pragma mark  发送指令

- (void)sendOpCodePkt:(struct NetComuDataPkt_t)pkt
{
    @synchronized(self) {
        if (mSocket.isConnected) {
            NSData *data_buf = [NSData dataWithBytes:&pkt length:NET_COMU_SIZE];
            [mSocket writeData:data_buf withTimeout:1 tag:0];
            memcpy(&mMsg_pkt, &pkt.data, MAX_NET_PKT_PAYLOAD);
        }
    }
}

- (void)sendOpCode:(int)op_code addr:(NSString*)addrStr data:(Byte*)data
{
    int addr = strtoul([[NSString stringWithFormat:@"0x%@", addrStr] UTF8String], 0, 0);
    [self sendOpCodePkt:get_package(op_code, &addr, data)];
}

- (void)searchLights
{
    [self sendOpCodePkt:get_package(OP_CODE_WHOAREYOU, NULL, NULL)];
}

- (void)turnOnLights:(NSString*)addr
{
    [self sendOpCode:OP_CODE_ALL_ON addr:addr data:NULL];
}

- (void)turnOffLights:(NSString*)addr
{
    [self sendOpCode:OP_CODE_ALL_OFF addr:addr data:NULL];
}

- (void)setLightBrightness:(int)percentage addr:(NSString*)addr
{
    
    Byte temp[3];
    memcpy(temp, mMsg_pkt.data, 3);
    
    switch (mMsg_pkt.op_code) {
		case OP_CODE_ONLY_WHITE:
            [self setLightOnlyWhite:addr brightness:percentage];
			break;
            
//		case OP_CODE_COLOR_CHANGE:
//            [UIColor colorWithHue:0 saturation:0 brightness:percentage / 100.0f alpha:0];
//            [self setLightColorRed:temp[0] green:temp[1] blue:temp[2] addr:addr];
//			break;
            
		case OP_CODE_RGB_TURN:
            [self startRGBTurn:temp[0] brightness:percentage addr:addr];
			break;
            
		case OP_CODE_RGB_BLINK:
            [self startRGBBlink:temp[0] brightness:percentage addr:addr];
			break;
            
		case OP_CODE_COLOR_SMOOTH:
			[self startColorSmooth:temp[0] brightness:percentage addr:addr];
			break;
            
		case OP_CODE_RGB_TURN_ONMIC:
			[self startRGBTurnOnMic:temp[0] brightness:percentage addr:addr];
			break;
            
		case OP_CODE_COLOR_SMOOTH_ONMIC:
			[self startColorSmoothOnMic:temp[0] brightness:percentage addr:addr];
			break;
            
		default:
              temp[0] = percentage;
              [self sendOpCode:OP_CODE_BRIGHTNESS addr:addr data:temp];
			break;
    }
}

- (void)setLightColorRed:(float)red green:(float)green blue:(float)blue addr:(NSString*)addr
{
    [self setLightColorR:(red * 255) g:(green * 255) b:(blue * 255) addr:addr];
}

- (void)setLightColorR:(int)red g:(int)green b:(int)blue addr:(NSString*)addr
{
    Byte temp[] = {(Byte)red, (Byte)green, (Byte)blue};
    [self sendOpCode:OP_CODE_COLOR_CHANGE addr:addr data:temp];
}

- (void)setLightOnlyWhite:(NSString*)addr brightness:(int)brightness
{
    Byte temp[] = {brightness, 0, 0};
    [self sendOpCode:OP_CODE_ONLY_WHITE addr:addr data:temp];
}

- (void)setLightOnlyRed:(NSString*)addr
{
    [self sendOpCode:OP_CODE_PURE_RED addr:addr data:NULL];
}

- (void)setLightOnlyGreen:(NSString*)addr
{
    [self sendOpCode:OP_CODE_PURE_GREEN addr:addr data:NULL];
}

- (void)setLightOnlyBlue:(NSString*)addr
{
    [self sendOpCode:OP_CODE_PURE_BLUE addr:addr data:NULL];
}

- (void)setPowerOffAfter:(u_int16_t)minute addr:(NSString*)addr
{
    Byte temp[] = {(Byte)(minute & 0xff), (Byte)(minute >> 8 & 0xff)};
    [self sendOpCode:OP_CODE_POWER_OFF_AFTER addr:addr data:temp];
}

- (void)setPowerOnAfter:(u_int16_t)minute addr:(NSString*)addr
{
    Byte temp[] = {(Byte)(minute & 0xff), (Byte)(minute >> 8 & 0xff)};
    [self sendOpCode:OP_CODE_POWER_ON_AFTER addr:addr data:temp];
}

// 开始 闪烁
- (void)startRGBBlink:(int)time brightness:(int)brightness addr:(NSString*)addr
{
    Byte temp[] = {time, brightness, 0};
    [self sendOpCode:OP_CODE_RGB_BLINK addr:addr data:temp];
}

// 开始RGB轮流 闪烁
- (void)startRGBTurn:(int)time brightness:(int)brightness addr:(NSString*)addr
{
    Byte temp[] = {time, brightness, 0};
    [self sendOpCode:OP_CODE_RGB_TURN addr:addr data:temp];
}

// 开始RGB颜色随机变化 闪烁
- (void) startColorSmooth:(int)time brightness:(int)brightness addr:(NSString*)addr
{
    Byte temp[] = {time, brightness, 0};
    [self sendOpCode:OP_CODE_COLOR_SMOOTH addr:addr data:temp];
}

// 开始 随着麦克风 RGB轮流 闪烁
- (void) startRGBTurnOnMic:(int)time brightness:(int)brightness addr:(NSString*)addr
{
    Byte temp[] = {time, brightness, 0};
    [self sendOpCode:OP_CODE_RGB_TURN_ONMIC addr:addr data:temp];
}

- (void)startColorSmoothOnMic:(int)time brightness:(int)brightness addr:(NSString*)addr
{
    Byte temp[] = {time, brightness, 0};
    [self sendOpCode:OP_CODE_COLOR_SMOOTH_ONMIC addr:addr data:temp];
}


#pragma mark - GCDAsyncSocket Delegate

- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
{
    NSLog(@"Socket did connect!");
    [mSocket performBlock:^{
        [mSocket enableBackgroundingOnSocket];
    }];
    [mSocket readDataWithTimeout:-1 tag:0];
    [self postNotificationName:ncLightConnected object:self];
    
    mDataProcessor = [[DataProcessor alloc] init];
    mDataProcessor.delegate = self;
}

- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
    NSLog(@"socket did disconnect->%@", err);
    mDataProcessor.delegate = nil;
    mDataProcessor = nil;
    
    if (err == nil || err.code == 57 || err.code == GCDAsyncSocketClosedError) {
        [self postNotificationName:ncLightDisconnect object:err];
    } else {
        [self postNotificationName:ncLightConnectionFailed object:err];
    }
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        sleep(2);
        [self connect];
    });
}

- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
    //    NSLog(@"发送完成！");
}

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    //    NSLog(@"didReadData->%@", data);
    [mSocket readDataWithTimeout:-1 tag:0];
    [mDataProcessor processInputData:data];
}

#pragma mark - DataProcessor Delegate

- (void)getCAN_msg:(msg_pkt)msg
{
    int addr;
    memcpy(&addr, msg.addr, 4);
    NSLog(@"msg op_code==>%i addr==>%x", msg.op_code, addr);
    
    if (msg.op_code == OP_CODE_IAM) {
        if (self.delegate && [self.delegate respondsToSelector:@selector(findTheLight:)]) {
            // 回到主线程发出Delegate
            dispatch_async(dispatch_get_main_queue(), ^{
                [self.delegate findTheLight:msg];
            });
        }
    }
    
    [self postNotificationName:ncLightMessge object:[NSData dataWithBytes:&msg length:MAX_NET_PKT_PAYLOAD]];
}

#pragma mark  发出通知

- (void)postNotificationName:(NSString *)aName object:(id)anObject
{
    // 回到主线程发出通知
    dispatch_async(dispatch_get_main_queue(), ^{
        [[NSNotificationCenter defaultCenter] postNotificationName:aName object:anObject];
    });
}

@end

struct NetComuDataPkt_t get_package(uint8_t op_code, void *addr, void *data)
{
    struct NetComuDataPkt_t msg;
    msg.magic1 = DATA_START;
    msg.magic2 = DATA_START;
    msg.magic3 = DATA_END;
    msg.magic4 = DATA_END;
    
    msg.data.op_code = op_code;
    
    if(addr != NULL) {
        memcpy(msg.data.addr, addr, 4);
    }
    if (data != NULL) {
        memcpy(msg.data.data, data, 3);
    }
    
    Byte temp[MAX_NET_PKT_PAYLOAD];
    memcpy(temp, &msg.data, MAX_NET_PKT_PAYLOAD);
    
    msg.check_sum = 0x0;
    for(int i= 0; i < MAX_NET_PKT_PAYLOAD; i++){
        msg.check_sum += temp[i];
    }
    
    return msg;
}